package com.invengo.testrfid.app.proxy.real;

import com.invengo.testrfid.app.entity.ReadTagEntity;
import com.invengo.testrfid.app.proxy.ProxyReadTag;
import com.invengo.testrfid.app.proxy.subject.SubjectReadTag;
import com.invengo.testrfid.app.utils.ByteConvertUtils;

import invengo.javaapi.core.BaseReader;
import invengo.javaapi.core.IMessageNotification;
import invengo.javaapi.core.MemoryBank;
import invengo.javaapi.core.Util;
import invengo.javaapi.handle.IMessageNotificationReceivedHandle;
import invengo.javaapi.protocol.IRP1.PowerOff;
import invengo.javaapi.protocol.IRP1.RXD_TagData;
import invengo.javaapi.protocol.IRP1.ReadTag;
import invengo.javaapi.protocol.IRP1.Reader;
import invengo.javaapi.protocol.IRP1.WriteEpc;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class RealReadTagInven2910 extends SubjectReadTag implements IMessageNotificationReceivedHandle {

    public static RealReadTagInven2910 realReadTagInven2910;
    private static Reader reader;
    private ProxyReadTag.ReadTagCallback readTagCallback;
    private ProxyReadTag.ReadTagAllDataCallbac readTagAllDataCallbac;
    private boolean isStopReadTag;

    public static RealReadTagInven2910 getInstance() {
        if (realReadTagInven2910 == null) {
            realReadTagInven2910 = new RealReadTagInven2910();
        }
        return realReadTagInven2910;
    }

    private static byte[] intToByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    /**
     * 连接读写器
     *
     * @param connectReaderStatue
     */
    @Override
    public void connectReader(final ProxyReadTag.ConnectReaderStatue connectReaderStatue) {


        if (reader != null && reader.isConnected()) {
            return;
        }

        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {

                // 两种设备使用的连接方法是不一样的。
                String address = "/dev/ttyS4" + "," + "115200";
                reader = new Reader("Reader1", "RS232", address);
                if (reader.connect()) {
                    reader.onMessageNotificationReceived.add(RealReadTagInven2910.this);
                    e.onNext("success");
                } else {
                    e.onNext("error");
                }
            }
        }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread());

        observable.subscribe(new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {

                if (s.contains("success")) {
                    connectReaderStatue.onConnectSuccess();
                } else {
                    connectReaderStatue.onConnectFailed();
                }
            }
        });
    }

    /**
     * 读取标签
     *
     * @param readTagCallback
     */
    @Override
    public void readTagTid(ProxyReadTag.ReadTagCallback readTagCallback) {

        if (reader == null || !reader.isConnected()) {

            readTagCallback.onFailed("读写器未连接，请链接读写器");
            connectReader(new ProxyReadTag.ConnectReaderStatue() {
                @Override
                public void onConnectSuccess() {

                }

                @Override
                public void onConnectFailed() {

                }
            });
            return;
        }

        //发送读卡指令，读取6C标签EPC
        ReadTag readTag = new ReadTag(ReadTag.ReadMemoryBank.TID_6C);
        boolean result = reader.send(readTag);
        if (result) {

            isStopReadTag = false;
            this.readTagCallback = readTagCallback;
        } else {
            readTagCallback.onFailed("读写器指令发送失败，请重试");
        }
    }

    /**
     * 停止读取标签
     *
     * @param stopReadCallback
     */
    @Override
    public void stopRead(ProxyReadTag.StopReadCallback stopReadCallback) {

        if (isStopReadTag) {
            return;
        }
        isStopReadTag = true;

        //发送关功放指令，停止读卡
        boolean result = reader.send(new PowerOff());
        if (result) {
            stopReadCallback.onStopSuccess();
        } else {
            stopReadCallback.onStopFailed();
        }
    }

    @Override
    public void disConnectReader(ProxyReadTag.DisConnectReaderStatue disConnectReaderStatue) {
        if (reader.isConnected()) {
//            reader.disConnect();
        }
    }

    @Override
    public void writeDataToEpc(String data, ProxyReadTag.WriteTagEpcCallback writeTagEpcCallback) {


        WriteEpc data_6C = new WriteEpc((byte) 0x00, intToByteArray(0000), intToByteArray(0x9999ffff));
        boolean result = reader.send(data_6C);
        if (result) {

            writeTagEpcCallback.onWriteSuccess();
        } else {

            writeTagEpcCallback.onWriteFailed();
        }
    }

    @Override
    public void writeDataToEpc(byte[] data, ProxyReadTag.WriteTagEpcCallback writeTagEpcCallback) {

        WriteEpc data_6C = new WriteEpc((byte) 0x00, intToByteArray(0000), data);
        boolean result = reader.send(data_6C);
        if (result) {

            writeTagEpcCallback.onWriteSuccess();
        } else {

            writeTagEpcCallback.onWriteFailed();
        }
    }

    @Override
    public void writeDataToEpc(byte[] data, byte[] epcData, ProxyReadTag.WriteTagEpcCallback writeTagEpcCallback) {

        WriteEpc data_6C = new WriteEpc((byte) 0x00, intToByteArray(0000), epcData,data, MemoryBank.TIDMemory);
        boolean result = reader.send(data_6C);
        if (result) {

            writeTagEpcCallback.onWriteSuccess();
        } else {

            writeTagEpcCallback.onWriteFailed();
        }
    }


    @Override
    public void readTagAllData(ProxyReadTag.ReadTagAllDataCallbac readTagAllDataCallbac) {

        if (reader == null || !reader.isConnected()) {

            readTagAllDataCallbac.onReadTagFailed("读写器未连接，请链接读写器");
            connectReader(new ProxyReadTag.ConnectReaderStatue() {
                @Override
                public void onConnectSuccess() {

                }

                @Override
                public void onConnectFailed() {

                }
            });
            return;
        }

        //发送读卡指令，读取6C标签EPC
        ReadTag readTag = new ReadTag(ReadTag.ReadMemoryBank.EPC_TID_UserData_6C);
        boolean result = reader.send(readTag);
        if (result) {

            isStopReadTag = false;
            this.readTagAllDataCallbac = readTagAllDataCallbac;
        } else {
            readTagAllDataCallbac.onReadTagFailed("读写器指令发送失败，请重试");
        }
    }

    /**
     * 读取标签结果返回
     *
     * @param baseReader
     * @param msg
     */
    @Override
    public void messageNotificationReceivedHandle(BaseReader baseReader,
                                                  IMessageNotification msg) {

        // 源代码这样写的
        if (msg instanceof RXD_TagData) {
            final RXD_TagData data = (RXD_TagData) msg;

            Observable<ReadTagEntity> observable = Observable.create(new ObservableOnSubscribe<ReadTagEntity>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<ReadTagEntity> e) throws Exception {

                    String tid = Util.convertByteArrayToHexString(data.getReceivedMessage().getTID());
//                    String epc = Util.convertByteArrayToHexString(data.getReceivedMessage().getEPC());
                    String epc =  ByteConvertUtils.byteArrayToStr(data.getReceivedMessage().getEPC());
                    String user = Util.convertByteArrayToHexString(data.getReceivedMessage().getUserData());

                    ReadTagEntity readTagEntity = new ReadTagEntity();
                    readTagEntity.setTid(tid);
                    readTagEntity.setEpc(epc);
                    readTagEntity.setUser(user);
                    readTagEntity.setTidData(data.getReceivedMessage().getTID());

                    e.onNext(readTagEntity);
                }
            }).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread());

            observable.subscribe(new Consumer<ReadTagEntity>() {
                @Override
                public void accept(@NonNull ReadTagEntity s) throws Exception {

                    if (readTagAllDataCallbac != null) {
                        readTagAllDataCallbac.onReadTagSuccess(s);
                    }
                    if (readTagCallback != null) {
                        readTagCallback.onReadSuccess(s.getTid());
                    }
                }
            });
        }
    }
}
